﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reactive.Linq;
using System.Text;

namespace QbservableCore.Serialization
{
    public class JsonToExpression
    {
        public static IQbservable Transform(JToken json, 
            IQbservableConvention convention,
            IQbservableTargetResolver targetResolver)
        {
            var arr = json as JArray;
            if (arr == null)
                throw new ArgumentException("json should be JArray");

            var root = (JObject)arr.First();
            string category = root.ExtractProperty(Consts.Json.Category, convention);
            string targetConvention = convention.FromKeyToConvention(Consts.Json.Target);
            if (category != targetConvention)
                throw new FormatException("Invalid json format (the root element's type should be Target)");

            var rootValue = root.ExtractProperty(Consts.Json.Value, convention);
            IQbservable qbs = targetResolver.ToQbservable(rootValue);
            arr.RemoveAt(0);

            TransformArray(arr, qbs.Expression, convention);
            return qbs;
        }

        private static void TransformArray(
            JArray arr,
            Expression exp, 
            IQbservableConvention convention)
        {
            foreach (JToken j in arr)
            {
                var innerArray = j as JArray;
                if(innerArray != null)
                {
                    throw new NotImplementedException();
                    //TransformArray(innerArray, exp); // ????
                }

                var jObj = j as JObject;
                if (jObj != null)
                {
                    string call = convention.FromExpressionTypeToConvention(ExpressionType.Call);
                    string category = jObj.ExtractProperty(Consts.Json.Category, convention);
                    if (category == call)
                    {
                        MethodCall.BuildExpression(jObj, exp, convention);
                    }
                }
           }
        }

    }
}
